package com.example.emos.wx.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.example.emos.wx.config.SystemConstants;
import com.example.emos.wx.controller.form.CheckinForm;
import com.example.emos.wx.db.mapper.*;
import com.example.emos.wx.db.pojo.TbCheckin;
import com.example.emos.wx.db.pojo.TbCity;
import com.example.emos.wx.db.pojo.TbFaceModel;
import com.example.emos.wx.exception.EmosException;
import com.example.emos.wx.service.CheckinService;
import com.example.emos.wx.task.EmailTask;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

/**
 * @ClassName CheckinServiceImpl
 * @Description TODO
 * @Author luowenhong
 * @Version 1.0
 **/
@Service
@Slf4j
@Scope("prototype")
public class CheckinServiceImpl implements CheckinService {
    @Autowired
    private TbCheckinMapper checkinMapper;

    @Autowired
    private TbHolidaysMapper holidaysMapper;

    @Autowired
    private TbWorkdayMapper workdayMapper;

    @Autowired
    private TbFaceModelMapper faceModelMapper;

    @Autowired
    private TbCityMapper cityMapper;

    @Autowired
    private SystemConstants systemConstants;

    @Autowired
    private TbUserMapper userMapper;

    @Autowired
    private EmailTask emailTask;

    @Value("${emos.face.checkinUrl}")
    private String checkinUrl;

    @Value("${emos.face.createFaceModelUrl}")
    private String createFaceModelUrl;

    @Value("${emos.code}")
    private String code;

    @Value("${emos.email.hr}")
    private String hrEmail;

    /**
     * 判断当天是否可以考勤
     *
     * @param
     * @author luowenhong
     */
    @Override
    public String ValidCanCheckin(Integer userId, String date) {
        boolean isWork = workdayMapper.isWorkday() != null ? true : false;
        boolean isHolidays = holidaysMapper.isHolidays() != null ? true : false;

        String type = "工作日";
        /** 判断当天类型 */
        if (DateUtil.date().isWeekend()) {
            type = "节假日";
        }
        if (isWork) {
            type = "工作日";
        } else if (isHolidays) {
            type = "节假日";
        }

        /** 判断当天能否考勤 */
        if ("工作日".equals(type)) {
            /** 判断现在是否处于考勤时段 */
            DateTime now = DateUtil.date();
            String start = DateUtil.today() + " " + systemConstants.attendanceStartTime;
            String end = DateUtil.today() + " " + systemConstants.attendanceEndTime;
            DateTime attendanceStart = DateUtil.parse(start);
            DateTime attendanceEnd = DateUtil.parse(end);
            if (now.isBefore(attendanceStart)) {
                return "今天的考勤未开始";
            } else if (now.isAfter(attendanceEnd)) {
                return "今天的考勤已结束";
            } else {
                HashMap hashMap = new HashMap();
                hashMap.put("userId", userId);
                hashMap.put("date", date);
                hashMap.put("start", start);
                hashMap.put("end", end);
                boolean bool = checkinMapper.isCheckin(hashMap) != null ? true : false;
                return bool ? "今天已考勤,不用重复考勤" : "可以考勤";
            }
        } else {
            return "今天为节假日，无需考勤";
        }
    }

    /**
     * 创建人脸模型
     * @author luowenhong
     * @date 2023/3/1 11:20
     * @param
     */
    @Override
    public void insertFaceModel(Integer userId, String path) {
        HttpRequest request = HttpUtil.createPost(createFaceModelUrl);
        request.form("photo", FileUtil.file(path));
        request.form("code",code);
        log.info(code);

        HttpResponse response = request.execute();
        if (response.getStatus() != 200){
            log.error("人脸识别服务异常");
            throw new EmosException("人脸识别服务异常");
        }else {
            String body = response.body();
            if ("无法识别出人脸".equals(body) || "照片中存在多张人脸".equals(body)) {
                throw new EmosException(body);
            }else {
                TbFaceModel faceModel = new TbFaceModel();
                faceModel.setUserId(userId);
                faceModel.setFaceModel(body);
                faceModelMapper.insertFaceModel(faceModel);
            }
        }

    }

    /**
     * 用户考勤
     *
     * @param
     * @author luowenhong
     * @date 2023/2/28 19:41
     */
    @Override
    public void UserCheckin(HashMap param) {
        /** 判断考勤类型  1-正常签到  2-迟到 */
        int status = 1;
        Date d1 = DateUtil.date();
        Date d2 = DateUtil.parse(DateUtil.today() + " " + systemConstants.attendanceTime);
        Date d3 = DateUtil.parse(DateUtil.today() + " " + systemConstants.attendanceEndTime);
        if (d1.compareTo(d2) <= 0) {
            status = 1;
        } else if (d1.compareTo(d2) > 0 && d1.compareTo(d3) < 0) {
            status = 2;
        } else{
            throw new EmosException("超出考勤时间段，无法考勤");
        }

        /** 判断考勤是否成功 */
        Integer userId =(Integer) param.get("userId");
        String faceModel = faceModelMapper.selectById(userId);

        if (faceModel == null) {
            throw new EmosException("不存在人脸模型");
        } else {
            /** 根据人脸识别结果判断考勤是否成功 */
            HttpRequest request = HttpUtil.createPost(checkinUrl);
            String path = param.get("path").toString();
            request.form("photo", FileUtil.file(path), "targetModel", faceModel);
            request.form("code",code);
            HttpResponse response = request.execute();
            if (response.getStatus() != 200) {
                log.error("人脸识别服务异常");
                throw new EmosException("人脸识别服务异常");
            }
            String body = response.body();
            if ("无法识别出人脸".equals(body) || "照片中存在多张人脸".equals(body)) {
                throw new EmosException(body);
            } else if ("False".equals(body)) {
                throw new EmosException(body);
            } else if ("True".equals(body)) {
                int risk = 1;
                CheckinForm form = (CheckinForm) param.get("form");
                String city= form.getCity();
                String district= form.getDistrict();
                String address= form.getAddress();
                String country= form.getCountry();
                String province= form.getProvince();
//                //查询城市简称
//                if (form.getCity() != null && form.getCity().length() > 0 && form.getDistrict() != null && form.getDistrict().length() > 0) {
//                    String cityCode = cityMapper.searchCode(form.getCity());
//                    //查询地区风险
//                    try {
//                        String url = "http://m." + cityCode + ".bendibao.com/news/yqdengji/?qu=" + form.getDistrict();
//                        Document document = Jsoup.connect(url).get();
//                        Elements elements = document.getElementsByClass(" list-detail");
//                        for (Element one : elements) {
//                            String result = one.text().split(" ")[1];
//                            if ("高风险".equals(result)) {
//                                risk = 3;
//                                //发送告警邮件
//                                HashMap<String, String> map = userMapper.searchNameAndDept(userId);
//                                String name = map.get("name");
//                                String deptName = map.get("dept_name");
//                                deptName = deptName != null ? deptName : "";
//                                SimpleMailMessage message = new SimpleMailMessage();
//                                message.setTo(hrEmail);
//                                message.setSubject("员工" + name + "身处高风险疫情地区警告");
//                                message.setText(deptName + "员工" + name + "，" + DateUtil.format(new Date(), "yyyy年MM月dd日") + "处于" + address + "，属于新冠疫情高风险地区，请及时与该员工联系，核实情况！");
//                                emailTask.sendAsync(message);
//                            } else if ("中风险".equals(result)) {
//                                risk = risk < 2 ? 2 : risk;
//                            }
//                        }
//                    } catch (IOException e) {
//                        log.error("执行异常", e);
//                        throw new EmosException("获取风险等级失败");
//                    }
//                }
//
                //保存签到记录
                TbCheckin entity = new TbCheckin();
                entity.setUserId(userId);
                entity.setAddress(address);
                entity.setCountry(country);
                entity.setProvince(province);
                entity.setCity(city);
                entity.setDistrict(district);
                entity.setStatus((byte) status);
                entity.setRisk(risk);
                entity.setDate(DateUtil.today());
                entity.setCreateTime(d1);
                checkinMapper.insertCheckin(entity);

            }
        }
    }

    /**
     * 一周的签到记录
     * @author luowenhong
     * @date 2023/3/2 21:05
     * @param
     */
    @Override
    public ArrayList<HashMap> searchWeekCheckin(HashMap hashmap) {
        ArrayList<HashMap> weekCheckin = userMapper.searchWeekCheckin(hashmap);
        ArrayList<String> holidaysList = holidaysMapper.searchHolidaysInRange(hashmap);
        ArrayList<String> workdayList = workdayMapper.searchWorkdayInRange(hashmap);

        DateTime startDate = DateUtil.parseDate(hashmap.get("startDate").toString());
        DateTime endDate = DateUtil.parseDate(hashmap.get("endDate").toString());
        DateRange range = DateUtil.range(startDate, endDate, DateField.DAY_OF_MONTH);
        ArrayList list = new ArrayList();

        range.forEach(one ->{
            /** 判断该天类型 */
            String type = "工作日";
            String date = one.toString("yyyy-MM-dd");
            if (one.isWeekend()){
                type = "节假日";
            }
            if (holidaysList != null && holidaysList.contains(date)){
                type = "节假日";
            }else if (workdayList != null && workdayList.contains(date)){
                type = "工作日";
            }

            String status = "";
            /** 判断今天之前所有天的考勤类型 */
            if ("工作日".equals(type) && DateUtil.compare(one, DateUtil.date()) <= 0){
                status = "缺勤";
                boolean flag = false;
                for(HashMap<String, String> map : weekCheckin){
                    if (map.containsValue(date)){
                        status = map.get("status");
                        flag = true;
                        break;
                    }
                }
                DateTime endTime = DateUtil.parse(DateUtil.today() + " " + systemConstants.attendanceEndTime);
                String today = DateUtil.today();
                /** 如果今天还未签到，则状态为空 */
                if (date.equals(today) && DateUtil.date().isBefore(endTime) && flag == false){
                    status="";
                }
            }

            HashMap map = new HashMap<>();
            map.put("date",date);
            map.put("status",status);
            map.put("type",type);
            map.put("day",one.dayOfWeekEnum().toChinese("周"));
            list.add(map);
        });

        return list;
    }

    @Override
    public ArrayList<HashMap> searchMonthCheckin(HashMap hashmap) {
        ArrayList<HashMap> list = this.searchWeekCheckin(hashmap);
        return list;
    }

    /**
     * 今天的签到记录
     * @author luowenhong
     * @date 2023/3/2 21:05
     * @param
     */
    @Override
    public HashMap searchTodayCheckin(Integer userId) {
        HashMap hashMap = userMapper.searchTodayCheckin(userId);
        return hashMap;
    }

    /**
     * 签到总天数
     * @author luowenhong
     * @date 2023/3/2 21:06
     * @param
     */
    @Override
    public long searchCheckinDays(Integer userId) {
        long days = userMapper.searchCheckinDays(userId);
        return days;
    }
}
